package com.teaching.teachingsupport.service.impl.teacherserviceimpl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.teaching.teachingsupport.common.pojo.dataobject.Course;
import com.teaching.teachingsupport.common.pojo.dataobject.Syllabus;
import com.teaching.teachingsupport.common.pojo.dataobject.SyllabusGrade;
import com.teaching.teachingsupport.common.pojo.dto.response.CourseResponse;
import com.teaching.teachingsupport.common.pojo.dto.response.SyllabusCreateDTO;
import com.teaching.teachingsupport.common.pojo.dto.response.SyllabusDTO;
import com.teaching.teachingsupport.common.utils.SecurityUtils;
import com.teaching.teachingsupport.mapper.studentviewmapper.CourseMapper;
import com.teaching.teachingsupport.mapper.SyllabusGradeMapper;
import com.teaching.teachingsupport.mapper.SyllabusMapper;
import com.teaching.teachingsupport.service.impl.UserServiceImpl;
import com.teaching.teachingsupport.service.service2.teacherservice.SyllabusService;
import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

@Service
@Slf4j
public class SyllabusServiceImpl implements SyllabusService {

    @Value("${file.upload.path:uploads/syllabus}")
    private String uploadPath;

    @Autowired
    private SyllabusMapper syllabusMapper;

    @Autowired
    private SyllabusGradeMapper syllabusGradeMapper;

    @Autowired
    private SecurityUtils securityUtils;

    @Autowired
    private UserServiceImpl userService;

    @Autowired
    private CourseMapper courseMapper;

    @Override
    public List<CourseResponse> getCourseList() {
        List<CourseResponse> courses = new ArrayList<>();
        
        CourseResponse course1 = new CourseResponse();
        course1.setCourseId(1L);
        course1.setCourseName("Java Programming");
        course1.setCourseCode("CS101");
        courses.add(course1);
        
        CourseResponse course2 = new CourseResponse();
        course2.setCourseId(2L);
        course2.setCourseName("Database Systems");
        course2.setCourseCode("CS102");
        courses.add(course2);
        
        return courses;
    }

    @Override
    @Transactional
    public boolean createSyllabus(SyllabusCreateDTO createDTO) {
        try {
            // 1. 获取当前用户ID
            Long userId = securityUtils.getCurrentUserId();

            // 2. 根据课程名称获取课程ID
            Long courseId = getCourseIdByName(createDTO.getCourseName());
            if (courseId == null) {
                log.error("课程不存在: {}", createDTO.getCourseName());
                throw new RuntimeException("课程不存在：" + createDTO.getCourseName());
            }

            // 3. 保存文件
            String fileName = saveFile(createDTO.getFile());

            // 4. 保存教学大纲信息
            Syllabus syllabus = new Syllabus();
            syllabus.setCourseId(courseId);
            syllabus.setFileName(fileName);
            syllabus.setFilePath(Paths.get(uploadPath, fileName).toString());
            syllabus.setStatus("PENDING");
            syllabus.setCreatorId(userId);
            syllabus.setCreateTime(LocalDateTime.now());
            syllabus.setUpdateTime(LocalDateTime.now());
            syllabusMapper.insert(syllabus);

            // 5. 保存年级关联信息
            List<String> formattedGrades = formatGrades(createDTO.getGrades());
            saveGrades(syllabus.getSyllabusId(), formattedGrades);

            return true;
        } catch (Exception e) {
            log.error("创建大纲失败", e);
            throw new RuntimeException("创建大纲失败：" + e.getMessage());
        }
    }

    @Override
    public List<SyllabusDTO> getSyllabusList(String status, String courseName) {
        // 1. 获取当前用户ID
        Long userId = securityUtils.getCurrentUserId();

        // 2. 查询教学大纲列表
        LambdaQueryWrapper<Syllabus> wrapper = new LambdaQueryWrapper<>();
        // 只查询当前用户的教学大纲
        wrapper.eq(Syllabus::getCreatorId, userId);
        
        if (status != null) {
            wrapper.eq(Syllabus::getStatus, status);
        }
        if (courseName != null) {
            Long courseId = getCourseIdByName(courseName);
            if (courseId != null) {
                wrapper.eq(Syllabus::getCourseId, courseId);
            }
        }
        List<Syllabus> syllabusList = syllabusMapper.selectList(wrapper);

        // 3. 转换为DTO
        return syllabusList.stream().map(this::convertToDTO).collect(Collectors.toList());
    }

    @Override
    public SyllabusDTO getSyllabusDetail(Long id) {
        // 1. 获取当前用户ID
        Long userId = securityUtils.getCurrentUserId();

        // 2. 查询教学大纲
        Syllabus syllabus = syllabusMapper.selectById(id);
        if (syllabus == null) {
            throw new RuntimeException("教学大纲不存在");
        }

        // 3. 验证权限
        if (!syllabus.getCreatorId().equals(userId)) {
            throw new RuntimeException("无权访问此教学大纲");
        }

        // 4. 查询适用年级
        List<String> grades = getGrades(id);
        
        // 5. 转换为DTO
        SyllabusDTO dto = convertToDTO(syllabus);
        dto.setGrades(grades);
        return dto;
    }

    @Override
    @Transactional
    public void updateSyllabus(Long id, SyllabusCreateDTO updateDTO) {
        try {
            // 1. 获取当前用户ID
            Long userId = securityUtils.getCurrentUserId();

            // 2. 查询原有教学大纲
            Syllabus syllabus = syllabusMapper.selectById(id);
            if (syllabus == null) {
                log.error("教学大纲不存在: {}", id);
                throw new RuntimeException("教学大纲不存在");
            }

            // 3. 验证权限
            if (!syllabus.getCreatorId().equals(userId)) {
                log.error("用户 {} 无权修改教学大纲 {}", userId, id);
                throw new RuntimeException("无权修改此教学大纲");
            }

            // 4. 根据课程名称获取课程ID
            Long courseId = getCourseIdByName(updateDTO.getCourseName());
            if (courseId == null) {
                log.error("课程不存在: {}", updateDTO.getCourseName());
                throw new RuntimeException("课程不存在：" + updateDTO.getCourseName());
            }

            // 5. 如果有新文件，保存新文件并删除旧文件
            if (updateDTO.getFile() != null) {
                String newFileName = saveFile(updateDTO.getFile());
                deleteFile(syllabus.getFilePath());
                syllabus.setFileName(newFileName);
                syllabus.setFilePath(Paths.get(uploadPath, newFileName).toString());
            }

            // 6. 更新基本信息
            syllabus.setCourseId(courseId);
            syllabus.setStatus("PENDING");
            syllabus.setUpdateTime(LocalDateTime.now());
            syllabusMapper.updateById(syllabus);

            // 7. 更新年级关联
            syllabusGradeMapper.delete(new LambdaQueryWrapper<SyllabusGrade>()
                    .eq(SyllabusGrade::getSyllabusId, id));
            List<String> formattedGrades = formatGrades(updateDTO.getGrades());
            saveGrades(id, formattedGrades);

        } catch (Exception e) {
            log.error("更新教学大纲失败: {}", id, e);
            throw new RuntimeException("更新教学大纲失败：" + e.getMessage());
        }
    }

    @Override
    public String previewSyllabusContent(Long id) {
        // 1. 获取当前用户ID
        Long userId = securityUtils.getCurrentUserId();

        // 2. 查询教学大纲
        Syllabus syllabus = syllabusMapper.selectById(id);
        if (syllabus == null) {
            throw new RuntimeException("教学大纲不存在");
        }

        // 3. 验证权限
        if (!syllabus.getCreatorId().equals(userId)) {
            throw new RuntimeException("无权预览此教学大纲");
        }

        // 4. 读取文件内容
        try {
            Path filePath = Paths.get(syllabus.getFilePath());
            return Files.readString(filePath);
        } catch (IOException e) {
            throw new RuntimeException("文件读取失败", e);
        }
    }

    private String saveFile(MultipartFile file) throws IOException {
        if (file == null || file.isEmpty()) {
            throw new RuntimeException("文件不能为空");
        }

        String originalFilename = file.getOriginalFilename();
        if (originalFilename == null || !originalFilename.toLowerCase().endsWith(".md")) {
            throw new RuntimeException("只支持.md格式的文件");
        }

        // 生成文件名：时间戳_UUID_原始文件名
        String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
        String uuid = UUID.randomUUID().toString().substring(0, 8);
        String fileName = String.format("%s_%s_%s", timestamp, uuid, originalFilename);

        // 确保目录存在
        Path uploadDir = Paths.get(uploadPath);
        if (!Files.exists(uploadDir)) {
            Files.createDirectories(uploadDir);
        }

        // 保存文件
        Path filePath = uploadDir.resolve(fileName);
        Files.copy(file.getInputStream(), filePath);

        return fileName;
    }

    private void deleteFile(String filePath) {
        if (filePath == null || filePath.isEmpty()) {
            return;
        }

        try {
            Path path = Paths.get(filePath);
            if (Files.exists(path)) {
                Files.delete(path);
                log.info("成功删除文件: {}", filePath);
            }
        } catch (IOException e) {
            log.error("删除文件失败: {}", filePath, e);
        }
    }

    private void saveGrades(Long syllabusId, List<String> grades) {
        if (grades != null && !grades.isEmpty()) {
            List<SyllabusGrade> gradeList = grades.stream()
                    .map(grade -> {
                        SyllabusGrade sg = new SyllabusGrade();
                        sg.setSyllabusId(syllabusId);
                        sg.setGrade(grade);
                        return sg;
                    })
                    .collect(Collectors.toList());
            gradeList.forEach(syllabusGradeMapper::insert);
        }
    }

    private List<String> getGrades(Long syllabusId) {
        List<SyllabusGrade> gradeList = syllabusGradeMapper.selectList(
                new LambdaQueryWrapper<SyllabusGrade>()
                        .eq(SyllabusGrade::getSyllabusId, syllabusId));
        return gradeList.stream()
                .map(SyllabusGrade::getGrade)
                .collect(Collectors.toList());
    }

    private SyllabusDTO convertToDTO(Syllabus syllabus) {
        SyllabusDTO dto = new SyllabusDTO();
        BeanUtils.copyProperties(syllabus, dto);
        
        // 直接从数据库获取课程信息
        Course course = courseMapper.selectById(syllabus.getCourseId());
        if (course != null) {
            dto.setCourseName(course.getCourseName());  // 使用中文名称
        }
        
        // 获取适用年级
        List<String> grades = getGrades(syllabus.getSyllabusId());
        dto.setGrades(grades);
        
        return dto;
    }

    // 根据课程名称获取课程ID
    private Long getCourseIdByName(String courseName) {
        // 从课程列表中查找匹配的课程
        return getCourseList().stream()
                .filter(course -> course.getCourseName().equals(courseName))
                .map(CourseResponse::getCourseId)
                .findFirst()
                .orElse(null);
    }

    private List<String> formatGrades(List<String> grades) {
        if (grades == null || grades.isEmpty()) {
            return List.of();
        }
        
        return grades.stream()
            .flatMap(grade -> Arrays.stream(grade.split("[,，]")))  // 处理可能的逗号分隔
            .map(String::trim)
            .map(grade -> {
                // 确保年级格式统一为"XXXX级"
                grade = grade.replaceAll("[^0-9]", "");  // 只保留数字
                if (grade.length() == 4) {
                    return grade + "级";
                }
                return null;
            })
            .filter(grade -> grade != null)
            .distinct()  // 去重
            .collect(Collectors.toList());
    }
} 